/**
 * 
 */
package neptune.manager.validator.rules.topology;

import java.util.ArrayList;

import neptune.manager.NeptuneManager;
import neptune.manager.model.topology.IPAddress;
import neptune.manager.model.topology.NetworkInterface;
import neptune.manager.model.topology.Node;
import neptune.manager.model.topology.Topology;
import neptune.manager.storage.ExperimentRepositoryException;
import neptune.manager.utils.Logger.MessageType;
import neptune.manager.validator.ValidatorResult;
import neptune.manager.validator.ValidatorRule;
import neptune.manager.validator.Validator.Status;

/**
 * @author Roberto Bifulco [RobertoBifulco.it] [info@robertoBifulco.it]
 * 
 */
public class IPAddressUniquenessRule extends ValidatorRule<Topology> {

	private NeptuneManager neptuneManager;

	public IPAddressUniquenessRule(NeptuneManager neptuneManager) {
		super();
		this.neptuneManager = neptuneManager;
	}

	@Override
	public String getName() {
		return "IPAddressUniquenessRule";
	}

	/**
	 * Verifica l'univocita' di un IP Address. Se la topologia passata come
	 * argomento e' gia' presente nel repository, la copia nel repository viene
	 * ignorata.
	 * 
	 */
	@Override
	protected ValidatorResult validationAlgorithm(Topology toValidate,
			ValidatorResult result) {
		ArrayList<IPAddress> usedIPs = new ArrayList<IPAddress>(0);

		try {
			/*
			 * Recupero di tutte le topologie
			 */
			String[] expIds = neptuneManager.getExperimentsRepository()
					.getExperiments();

			// Creazione array contenente tutte le topologie compresa quella
			// attuale
			Topology[] topologies = new Topology[expIds.length + 1];
			topologies[topologies.length - 1] = toValidate;
			for (int i = 0; i < topologies.length - 1; i++) {
				topologies[i] = neptuneManager.getExperiment(expIds[i])
						.getTopology();
				if (topologies[i] != null) {
					if (toValidate.getName().equals(topologies[i].getName())) {
						topologies[i] = null; // Se questa topologia e' presente
						// nel repository, ignora la
						// copia in repository
					}
				}
			}
			/*
			 * ----
			 */

			for (Topology topology : topologies) {
				if (topology == null)
					continue;

				for (Node node : topology.getNodes()) {
					for (NetworkInterface netIf : node.getInterfaces()) {
						for (IPAddress ipAddr : netIf.getIpAddresses()) {
							if (usedIPs.contains(ipAddr)) {
								result.setStatus(Status.ERROR);
								result
										.getLog()
										.addMessage(
												"Duplicated IP address '"
														+ ipAddr
														+ "' in interface '"
														+ netIf
																.getInterfaceName()
														+ "', node '"
														+ node.getId()
														+ "'. Error raised during topology '"
														+ topology.getName()
														+ "' examination.",
												MessageType.ERROR);
							} else
								usedIPs.add(ipAddr);
						}
					}
				}
			}

		} catch (ExperimentRepositoryException e) {
			result.setStatus(Status.ERROR);
			result.getLog().addMessage(
					"Unable to verify IP Addresses uniqueness. Cause: "
							+ e.getMessage(), MessageType.ERROR);
		}

		return result;
	}

}
